package com.mpgame.core.model;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.mpgame.core.status.StatusBase;
import com.mpgame.core.status.StatusType;
import com.mpgame.core.utils.MReport;
import com.mpgame.core.utils.MRules;

import lombok.Data;

@Data
public class Monster {
    private final int level, familyId, meleeAtk, magicAtk, meleeDef, magicDef, speed, health;
    private int curMeleeAtk, curMagicAtk, curMeleeDef, curMagicDef, curSpeed, curHealth;
    private final Map<String, Integer> curReinforces;
    private final Skill skill1, skill2, skill3, skill4;
    private Skill curSkill;
    private double curAccuracy = 1.0;
    private Monster curOpponent;
    private final Map<StatusType, StatusBase> curStatus;

    /** 引擎内部区分码 */
    private int engineIdx;
    /** 怪物名字标识 */
    private String identifier;

    public Monster(
            int level,
            int familyId,
            int meleeAtk,
            int magicAtk,
            int meleeDef,
            int magicDef,
            int speed,
            int health,
            Skill skill1,
            Skill skill2,
            Skill skill3,
            Skill skill4) {
        this.level = level;
        this.familyId = familyId;
        this.meleeAtk = meleeAtk;
        this.magicAtk = magicAtk;
        this.meleeDef = meleeDef;
        this.magicDef = magicDef;
        this.speed = speed;
        this.health = health;
        this.skill1 = skill1;
        this.skill2 = skill2;
        this.skill3 = skill3;
        this.skill4 = skill4;
        this.curStatus = new ConcurrentHashMap<>();
        this.curReinforces = new ConcurrentHashMap<>();
        curReinforces.put("meleeAtk", 0);
        curReinforces.put("magicAtk", 0);
        curReinforces.put("meleeDef", 0);
        curReinforces.put("magicDef", 0);
        curReinforces.put("speed", 0);
        curReinforces.put("accuracy", 0);

        this.curMeleeAtk = meleeAtk;
        this.curMagicAtk = magicAtk;
        this.curMeleeDef = meleeDef;
        this.curMagicDef = magicDef;
        this.curSpeed = speed;
        this.curHealth = health;
    }

    /** 添加异常效果 */
    public void addStatus(StatusBase status) {
        curStatus.put(status.getStatusType(), status.setMOwner(this).setMOpponent(curOpponent));
    }

    /** 移除异常效果 */
    public void removeStatus(StatusBase status) {
        curStatus.remove(status.getStatusType());
    }

    /** 清除所有异常效果 */
    public void clearStatus() {
        curStatus.clear();
    }

    /** 应用异常状态效果 */
    public void doStatusRound() {
        for (StatusBase status : curStatus.values()) {
            status.Consume();
        }
    }

    /** 受伤方法 */
    public void takeHurt(Damage damage) {
        int causedDamageAmount = calcDamage(damage);
        setCurHealth(Math.max(getCurHealth() - causedDamageAmount, 0));
        MReport.Report(getIdentifier() + "受到" + causedDamageAmount + "点伤害，当前血量：" + getCurHealth());
    }
    private int calcDamage(Damage damage){
        int res = 0;
        if(damage.getType() == DamageType.MELEE){
            res = Math.max(damage.getAmount() / MRules.getReinforcedValue(getCurMeleeDef(), getCurReinforces().get("meleeDef")), 1);
        }else if(damage.getType() == DamageType.MAGIC){
            res = Math.max(damage.getAmount() / MRules.getReinforcedValue(getCurMagicDef(), getCurReinforces().get("magicDef")), 1);
        }else{
            res = damage.getAmount();
        }
        return res;
    }

    /** 治疗方法 */
    public void takeHeal(int heal) {
        this.curHealth = Math.min(this.curHealth + heal, this.health);
    }
    /** 强化方法 */
    public boolean reinforce(String type, int level){
        if(curReinforces.containsKey(type)){
            curReinforces.put(type, Math.clamp(curReinforces.get(type) + level, -6, 6));
            return true;
        }
        return false;
    }

    public boolean isAlive() {
        return this.curHealth > 0;
    }

    /** 根据index设置当前出招技能，若超出1~4则视为自动选择技能 */
    public void setCurSkillByIndex(int index) {
        switch (index) {
            case 1:
                this.curSkill = this.skill1;
                break;
            case 2:
                this.curSkill = this.skill2;
                break;
            case 3:
                this.curSkill = this.skill3;
                break;
            case 4:
                this.curSkill = this.skill4;
                break;
            default:
                this.curSkill = autoChooseSkill();
                break;
        }
    }
    public int[] getReinforceArray(){
        return new int[]{
            this.curReinforces.get("meleeAtk"),
            this.curReinforces.get("magicAtk"),
            this.curReinforces.get("meleeDef"),
            this.curReinforces.get("magicDef"),
            this.curReinforces.get("speed"),
            this.curReinforces.get("accuracy"),
        };
    }
    /** 自动选择一个技能 */
    private Skill autoChooseSkill(){
        if(skill1 != null && skill1.getCurPp() > 0) return skill1;
        if(skill2 != null && skill2.getCurPp() > 0) return skill2;
        if(skill3 != null && skill3.getCurPp() > 0) return skill3;
        if(skill4 != null && skill4.getCurPp() > 0) return skill4;
        return null;
    }
}
